package com.imooc.controller;

import com.imooc.pojo.Users;
import com.imooc.pojo.bo.ShopcartBO;
import com.imooc.pojo.bo.UserBO;
import com.imooc.pojo.vo.UsersVO;
import com.imooc.service.UserService;
import com.imooc.utils.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.spring.web.json.Json;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

//@Controller
@RestController
@RequestMapping("passport")
@Api(value = "注册登录",tags = {"用于注册登录的相关接口"})   // 为Controller添加相关的文字描述信息
public class PassportController extends BaseController{

    @Autowired
    private UserService userService;
    @Autowired
    private RedisOperator redisOperator;

    /*
    * @RequestParam : 代表是一种请求类型的参数，而不是路径参数
    * */
    @ApiOperation(value="用户名是否存在",notes = "用户名是否存在?",httpMethod = "GET")  // 用于去阐述当前方法的含义
    @GetMapping("/usernameIsExist")
    public IMOOCJSONResult usernameIsExist(@RequestParam String username){
        /*
        1. 判断用户名不能为空
        isBlank 判断是否为null的同时可以额外判断是否为""字符串
        * */
        if(StringUtils.isBlank(username)){
            return  IMOOCJSONResult.errorMsg("用户名不能为空");
        }
        /*
        * 2. 查找注册的用户名是否存在
        * */
        boolean isExist = userService.queryUsernameIsExist(username);
        if(isExist){
            return IMOOCJSONResult.errorMsg("用户名已经存在");
        }
        /*
        * 3. 请求成功，用户名无重复
        * */
        return IMOOCJSONResult.ok();
    }

    /**
    * 前端传来的是一个Json对象，因此使用 @RequestBody 表明前端传来的是一个Json对象
    * 对请求体中寻找
    * */
    @ApiOperation(value="用户注册",notes = "用户注册?",httpMethod = "POST")
    @PostMapping("/regist")
    public IMOOCJSONResult regist(@RequestBody UserBO userBo,
                                  HttpServletRequest request,
                                  HttpServletResponse response){
        String username = userBo.getUsername();
        String password = userBo.getPassword();
        String confirmPwd = userBo.getConfirmPassword();
        /*
        * 1. 判断用户名和密码不为空
        * */
        if(StringUtils.isBlank(username) || StringUtils.isBlank(password) || StringUtils.isBlank(confirmPwd)){
            return IMOOCJSONResult.errorMsg("用户名或密码不能为空");
        }
        /*
        * 2. 查询用户名是否存在
        * */
        boolean isExist = userService.queryUsernameIsExist(username);
        if(isExist){
            return IMOOCJSONResult.errorMsg("用户名已经存在");
        }
        /*
        * 3. 判断密码长度不能少于6位
        * */
        if(password.length() < 6){
            return IMOOCJSONResult.errorMsg("密码长度不能少于6位");
        }
        /*
        * 4. 判断两次密码是否一致
        * */
        if(!password.equals(confirmPwd)){
            return IMOOCJSONResult.errorMsg("两次密码输入不一致");
        }
        /*
        * 5. 实现注册
        * */
        Users userResult = userService.createUser(userBo);

        // 这个之前是用于 忽略掉一些不必要的值,现在使用了UserVo ,就没有必要使用该函数了
        //userResult = setNullProperty(userResult);

        /**实现用户的redis会话
         * 1.生成一个tokenId
         * 2.存入Redis中
         * */
        UsersVO usersVo = conventUsersVO(userResult);

        /*
        * isEncode : 表示加密
        * */
        CookieUtils.setCookie(request, response, "user",
                JsonUtils.objectToJson(usersVo), true);

        // 同步购物车数据
        syncShopCardData(userResult.getId(),request,response);


        return IMOOCJSONResult.ok();
    }






    @ApiOperation(value = "用户登录", notes = "用户登录", httpMethod = "POST")
    @PostMapping("/login")
    public IMOOCJSONResult login(@RequestBody UserBO userBO,
                                 HttpServletRequest request,
                                 HttpServletResponse response) throws Exception {

        String username = userBO.getUsername();
        String password = userBO.getPassword();

        // 0. 判断用户名和密码必须不为空
        if (StringUtils.isBlank(username) ||
                StringUtils.isBlank(password)) {
            return IMOOCJSONResult.errorMsg("用户名或密码不能为空");
        }

        // 1. 实现登录
        Users userResult = userService.queryUserForLogin(username,
                MD5Utils.getMD5Str(password));

        if (userResult == null) {
            return IMOOCJSONResult.errorMsg("用户名或密码不正确");
        }

       // userResult = setNullProperty(userResult);

        UsersVO usersVO = conventUsersVO(userResult);

        CookieUtils.setCookie(request, response, "user",
                JsonUtils.objectToJson(usersVO), true);
        // 同步购物车数据
        syncShopCardData(userResult.getId(),request,response);

        return IMOOCJSONResult.ok(userResult);
    }

    /**
     * 注册/登录成功后,同步cookie和redis中的购物车数据
     */
    private void syncShopCardData(String userId,HttpServletRequest request,
                                  HttpServletResponse response) {
        /**
         * 1. redis中无数据,且cookie中的购物车为空,不做任何处理
         * 2. redis中无数据,cookie中的购物车不为空,将cookie中的购物车同步到redis中(直接放入)
         * 3. redis中有数据,cookie中的购物车为空,则将redis中的购物车同步到cookie中(直接覆盖本地cookie)
         * 4. redis中有数据,cookie中的购物车也不为空,
         *                  如果cookie中的某个商品在redis中存在,以cookie为主.(参考京东)
         * 5. 同步到redis后,需要覆盖本地cookie购物车的数据,保证本地cookie和redis中的数据一致性
         */
        // 从redis中获取购物车数据
        String shopCartJsonRedis = redisOperator.get(FOODIE_SHOPCART+":"+userId);
        // 从cookie中获取购物车数据
        String shopCartStrCookie = CookieUtils.getCookieValue(request,
                FOODIE_SHOPCART,true);
        if(StringUtils.isBlank(shopCartJsonRedis)){
            // redis为空,cookie不为空
            if(StringUtils.isNotBlank(shopCartStrCookie)){
                redisOperator.set(FOODIE_SHOPCART+":"+userId,shopCartStrCookie);
            }
            // redis为空,cookie为空 不做任何操作
        }else{
            // redis不为空,cookie不为空,合并cookie和redis中购物车的商品数据(同一商品,覆盖Redis)
            if(StringUtils.isNotBlank(shopCartStrCookie)) {
                /**
                 * 1. 已经存在的商品,把cookie中对应的数量覆盖到redis中
                 * 2. 该项商品标记为待删除,统一放入一个待删除的List中
                 * 3. 从cookie中清理所有的待删除List
                 * 4. 合并Redis和Cookie中的数据
                 * 5. 更新到Redis和Cookie中
                 */
                List<ShopcartBO> shopCartListRedis = JsonUtils.jsonToList(shopCartJsonRedis,ShopcartBO.class);
                List<ShopcartBO> shopCartListCookie = JsonUtils.jsonToList(shopCartStrCookie,ShopcartBO.class);

                // 待删除List
                List<ShopcartBO> pendingDeleteList = new ArrayList<>();
                // 循环以Redis为主
                for(ShopcartBO redisShopCart : shopCartListRedis){
                    String redisSpecId = redisShopCart.getSpecId();
                    for(ShopcartBO cookieShopCart: shopCartListCookie){
                        String cookieSpecId = cookieShopCart.getSpecId();
                        if(redisSpecId.equals(cookieSpecId)){
                            // cookie中的购买数量 覆盖 redis中的购买数量
                            redisShopCart.setBuyCounts(cookieShopCart.getBuyCounts());
                            // 将cookie中的商品放入待删除列表,用于最后的删除与合并
                            pendingDeleteList.add(cookieShopCart);
                        }
                    }
                }
                // 从现有Cookie中删除对应的覆盖过的商品数据
                shopCartListCookie.removeAll(pendingDeleteList);
                // 合并两个购物车
                shopCartListRedis.addAll(shopCartListCookie);
                // 更新到Redis和Cookie
                CookieUtils.setCookie(request,response,
                        FOODIE_SHOPCART,JsonUtils.objectToJson(shopCartListRedis));

                redisOperator.set(FOODIE_SHOPCART+":"+userId,JsonUtils.objectToJson(shopCartListRedis));

            }else {
                // redis不为空,cookie为空
                CookieUtils.setCookie(request,response,
                        FOODIE_SHOPCART,shopCartJsonRedis);
            }

        }
    }

    private Users setNullProperty(Users userResult) {
        userResult.setPassword(null);
        userResult.setMobile(null);
        userResult.setEmail(null);
        userResult.setCreatedTime(null);
        userResult.setUpdatedTime(null);
        userResult.setBirthday(null);
        return userResult;
    }

    @ApiOperation(value = "用户退出登录", notes = "用户退出登录", httpMethod = "POST")
    @PostMapping("/logout")
    public IMOOCJSONResult logout(@RequestParam String userId,
                                  HttpServletRequest request,
                                  HttpServletResponse response) {

        // 清除用户的相关信息的cookie
        CookieUtils.deleteCookie(request, response, "user");

        // 用户退出登录，清除redis中的会话信息
        redisOperator.del(REDIS_USER_TOKEN+":"+userId);
        // 分布式会话中需要清除用户数据
        CookieUtils.deleteCookie(request, response, FOODIE_SHOPCART);

        return IMOOCJSONResult.ok();
    }


}
